package com.tanhua.manage.service;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.manage.domain.AnalysisByDay;
import com.tanhua.manage.mapper.AnalysisByDayMapper;
import com.tanhua.manage.mapper.LogMapper;
import com.tanhua.manage.utils.ComputeUtil;
import com.tanhua.manage.vo.AnalysisSummaryVo;
import com.tanhua.manage.vo.AnalysisUsersVo;
import com.tanhua.manage.vo.DataPointVo;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

@Service
public class AnalysisService extends ServiceImpl<AnalysisByDayMapper, AnalysisByDay> {

    /**
     * 接口名称：概要统计信息
     */
    public ResponseEntity<Object> summary() {
        //1. 查询累计用户数
        //SELECT SUM(num_registered) num_registered FROM tb_analysis_by_day
        AnalysisByDay analysisByDay = query().select("SUM(num_registered) num_registered").one();
        Integer numRegistered = analysisByDay.getNumRegistered();

        //String now = "2021-03-08";
        //String yes = "2021-03-07";

        Date date = new Date();
        String now = new SimpleDateFormat("yyyy-MM-dd").format(date);
        String yes = ComputeUtil.offsetDay(date,-1);

        //2. 查询今日：新增用户、登陆次数、活跃用户
        // SELECT * FROM tb_analysis_by_day WHERE record_date='2021-03-08'
        AnalysisByDay todayAnalysis = query().eq("record_date", now).one();
        Integer todayRegister = todayAnalysis.getNumRegistered();
        Integer todayNumLogin = todayAnalysis.getNumLogin();
        Integer todayNumActive = todayAnalysis.getNumActive();

        //3. 查询昨日：新增用户、登陆次数、活跃用户
        AnalysisByDay yesAnalysis = query().eq("record_date", yes).one();
        Integer yesRegister = yesAnalysis.getNumRegistered();
        Integer yesNumLogin = yesAnalysis.getNumLogin();
        Integer yesNumActive = yesAnalysis.getNumActive();

        //4. 查询过去7天、30天活跃用户
        long day7 = this.baseMapper.findNumActiveByDate(ComputeUtil.offsetDay(date,-7),now);
        long day30 = this.baseMapper.findNumActiveByDate(ComputeUtil.offsetDay(date,-30),now);

        //5、创建返回的vo对象
        AnalysisSummaryVo vo = new AnalysisSummaryVo();
        // 累计用户数
        vo.setCumulativeUsers(numRegistered.longValue());
        // 设置今日：新增用户、登陆次数、活跃用户
        vo.setNewUsersToday(todayRegister.longValue());
        vo.setLoginTimesToday(todayNumLogin.longValue());
        vo.setActiveUsersToday(todayNumActive.longValue());
        // 设置涨跌率：新增用户、登陆次数、活跃用户
        vo.setNewUsersTodayRate(ComputeUtil.computeRate(todayRegister,yesRegister));
        vo.setLoginTimesTodayRate(ComputeUtil.computeRate(todayNumLogin,yesNumLogin));
        vo.setActiveUsersTodayRate(ComputeUtil.computeRate(todayNumActive,yesNumActive));

        // 设置过去7天、30天活跃用户
        vo.setActivePassMonth(day7);
        vo.setActivePassWeek(day30);

        return ResponseEntity.ok(vo);
    }

    @Autowired(required = false)
    private LogMapper logMapper;
    @Autowired(required = false)
    private AnalysisByDayMapper analysisByDayMapper;

    public void analysis() {
        //1. 获取当前时间
        Date date = new Date();
        String now = new SimpleDateFormat("yyyy-MM-dd").format(date);

        //2. 根据当前时间查询日表
        AnalysisByDay analysisByDay = query().eq("record_date", now).one();
        //3. 如果没有查询到今日统计数据，就执行插入
        if (analysisByDay == null) {
            analysisByDay = new AnalysisByDay();
            analysisByDay.setNumRetention1d(0);
            analysisByDay.setNumActive(0);
            analysisByDay.setNumLogin(0);
            analysisByDay.setNumRegistered(0);
            analysisByDay.setCreated(new Date());
            analysisByDay.setUpdated(new Date());
            analysisByDay.setRecordDate(date);
            // 保存
            analysisByDayMapper.insert(analysisByDay);
        }
        // 获取昨天的时间
        String yes = ComputeUtil.offsetDay(date, -1);

        //4. 更新日表
        //4.1 查询新注册用户数
        Long numRegister = logMapper.queryNumsByType("0102",now);
        //4.2 登陆次数
        Long numLogin = logMapper.queryNumsByType("0101",now);
        //4.3 活跃用户总数
        Long numActive = logMapper.queryNumsByDate(now);
        //4.4 次日留存 （昨天注册，今天登陆）
        Long numRetention1d = logMapper.queryNumRetention1d(now,yes);

        //4.5 设置查询的数据到日表对象中
        analysisByDay.setNumRegistered(numRegister.intValue());
        analysisByDay.setNumLogin(numLogin.intValue());
        analysisByDay.setNumActive(numActive.intValue());
        analysisByDay.setNumRetention1d(numRetention1d.intValue());
        analysisByDay.setUpdated(new Date());
        //4.6 更新日表
        analysisByDayMapper.updateById(analysisByDay);
    }

    public AnalysisUsersVo queryAnalysisUsersVo(Long sd, Long ed, Integer type) {
        DateTime startDate = DateUtil.date(sd);
        DateTime endDate = DateUtil.date(ed);
        AnalysisUsersVo analysisUsersVo = new AnalysisUsersVo();
        analysisUsersVo.setThisYear(queryDataPointVos(startDate,endDate,type));
        analysisUsersVo.setLastYear(queryDataPointVos(DateUtil.offset(startDate, DateField.YEAR,-1),DateUtil.offset(endDate,DateField.YEAR,-1),type));
        return analysisUsersVo;
    }
    private List<DataPointVo> queryDataPointVos(DateTime sd, DateTime ed, Integer type) {
        String startDate = sd.toDateStr();
        String endDate = ed.toDateStr();
        String column = null;
        switch (type){
            case 101:
                column = "num_registered";
                break;
            case 102:
                column = "num_active";
                break;
            case 103:
                column = "num_retention1d";
                break;
            default:
                column = "num_active";
                break;
        }
        List<AnalysisByDay> analysisByDayList = super.list(Wrappers.<AnalysisByDay>query()
                .select("record_date , " + column + " as num_active")
                .ge("record_date",startDate)
                .le("record_date",endDate));
        return analysisByDayList.stream().map(analysisByDay -> new DataPointVo(DateUtil.date(analysisByDay.getRecordDate()).toDateStr()
        ,analysisByDay.getNumActive().longValue())).collect(Collectors.toList());
    }
}